#define PROCESS_POOL_HEADER

#ifdef PROCESS_POOL_HEADER

#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/wait.h>
#include "Task.hpp"

class Channel
{
public:
    Channel(int pid, int fd) : _pid(pid), _fd(fd)
    {
        _name = "Channel : pid: " + std::to_string(pid) + "fd: " + std::to_string(fd);
    }
    void Send(int code) //接受外部传入的任务码
    {
        write(_fd,&code,sizeof(code));
    }
    void Close()
    {
        close(_fd);
    }
    void Wait()
    {
        int n = waitpid(_pid,nullptr,0);
        (void)n;
    }
    const std::string& name(){return _name;}
    int pid(){return _pid;}
    int fd(){return _fd;}
private:
    std::string _name;
    int _pid;
    int _fd;
};

class ChannelManager
{
public:
    void InsertChannel(int subid, int fd)
    {
        _cm.emplace_back(subid, fd);
    }
    Channel& Select()
    {
        _index += 1;
        _index %= _cm.size();
        return _cm[_index];
    }
    void CloseAll()
    {
        // for(auto& au : _cm)
        // {
        //     au.Close();
        //     std::cout << "关闭: " << au.name() << std::endl;
        // }
        //必须要将继承下来的父进程的写端全部关闭
        for(int i = 0 ; i<_cm.size() ; i++)
        {
            _cm[i].Close();
        }
    }
    void WaitAll()
    {
        for(auto& au : _cm)
        {
            au.Wait();
            std::cout << "回收: " << au.name() << std::endl;
        }
    }
    void ClearAll()
    {
        for(auto& au : _cm)
        {
            au.Close();
            std::cout << "关闭: " << au.name() << std::endl;
            au.Wait();
            std::cout << "回收: " << au.name() << std::endl;
        }
    }
private:
    std::vector<Channel> _cm;
    int _index = 0;
};

const int channelNum = 5;
class ProcessPool
{
public:
    void Work(int subid, int fd) //子进程从管道里读取信号
    {
        int code = 0;
        while(1)
        {
            int n = read(fd,&code,sizeof(code));
            if(n > 0)
            {
                //if(sizeof(n) != sizeof(code))
                if(n != sizeof(code))
                    continue;
                _tm.Execute(code);
                exit(0); //必须要退出!!!
            }
            else if (n == 0)
            {
                std::cout << "file end , child exit" << std::endl;
                break;
            }
            else
            {
                std::cout << "read fail , child exit\n" ;
                break; 
            }
        }
    }
    bool Start()
    {
        for (int i = 0; i < channelNum; i++)
        {
            int arr[2] = {0};
            int rp = pipe(arr);
            if (rp < 0)
            {
                std::cout << "creation of pipe fail";
                return false;
            }
            int subId = fork();
            if (subId == 0) // child
            {
                close(arr[1]);
                std::cout << "创建管道 , pid=" << getpid() << "\n";
                Work(subId, arr[0]); 
                close(arr[0]);
            }
            else if (subId > 0) // father
            {
                close(arr[0]);
                _cm.InsertChannel(subId, arr[1]);
            }
            else
            {
                std::cout << "creation of subprocess fail";
                return false;
            }
        }
        return true;
    }
    void Run()
    {
        //1,选择一个信道
        Channel c = _cm.Select();
        std::cout << "选择一个信道 , pid= " << c.pid() << " fd=" << c.fd() << std::endl;
        //2,决定任务码
        int code = _tm.SelecTask();
        std::cout << "发放任务,任务码= " << code;
        //3,派发任务码
        c.Send(code);
        std::cout << "\n";
    }
    void Clear()
    {
         _cm.CloseAll();
         _cm.WaitAll();
        //_cm.ClearAll();
    }
private:
    ChannelManager _cm;
    TaskManager _tm;
    int size;
};
#endif